cmake_minimum_required(VERSION 3.5)
project(perception)

# Default to C99
if(NOT CMAKE_C_STANDARD)
  set(CMAKE_C_STANDARD 99)
endif()

# Default to C++14
if(NOT CMAKE_CXX_STANDARD)
  set(CMAKE_CXX_STANDARD 14)
endif()

if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
  add_compile_options(-Wall -Wextra -Wpedantic -O2)
endif()

if(GDB)
  set(CMAKE_BUILD_TYPE "Debug")
  add_compile_options(-Wall -Wextra -Wpedantic -Wno-unused-parameter -ggdb)
else()
  set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS} -O3  -Wall")
  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O3  -Wall")
endif()
# 1. add ROS2 dependency
find_package(rclcpp_action REQUIRED)
find_package(ament_cmake REQUIRED)
find_package(rclcpp REQUIRED)
find_package(rclcpp_components REQUIRED)
find_package(std_msgs REQUIRED)
find_package(sensor_msgs REQUIRED)
find_package(nav_msgs REQUIRED)
find_package(visualization_msgs REQUIRED)
find_package(msg_interfaces REQUIRED)
find_package(projection REQUIRED)
# find_package(backward_ros REQUIRED)
find_package(Eigen3 REQUIRED)
find_package(OpenCV REQUIRED)
find_package(PCL 1.7 REQUIRED)
find_package(pcl_conversions REQUIRED)
find_package(Boost 1.54 REQUIRED)

# 2. add protobuf library
set(Protobuf_PREFIX_PATH
    "/usr/local/protobuf/include"            
    "/usr/local/protobuf/lib"             
    "/usr/local/protobuf/bin" )
list(APPEND CMAKE_PREFIX_PATH "${Protobuf_PREFIX_PATH}")
message(STATUS ${CMAKE_PREFIX_PATH})
find_package(Protobuf REQUIRED)
if(PROTOBUF_FOUND)
    message(STATUS "protobuf library found")
else()
    message(FATAL_ERROR "protobuf library is needed but cant be found")
endif()

# 添加第三方库
#[[if(CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "aarch64")
    message("this is aarch64 cpu")
    set(lib_path ${PROJECT_SOURCE_DIR}/third_libs/aarch64)
    set(lib_ ${lib_path}/spdlog/libspdlog.a)
elseif(CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "x86_64")
    message("this is x86_64 cpu")
    set(lib_path ${PROJECT_SOURCE_DIR}/third_libs/x86)
    set(lib_ ${lib_path}/spdlog/libspdlog.a)
endif()]]

# add INCLUDE directories
include_directories(
  ${CMAKE_CURRENT_SOURCE_DIR}
  ${CMAKE_CURRENT_BINARY_DIR}
  ${CMAKE_CURRENT_BINARY_DIR}/proto  # where the protobuf will be compiled into
  ${PROTOBUF_INCLUDE_DIRS}
  ${rclcpp_INCLUDE_DIRS}
  ${std_msgs_INCLUDE_DIRS}
  ${sensor_msgs_INCLUDE_DIRS}
  ${visualization_msgs_INCLUDE_DIRS}
  ${nav_msgs_INCLUDE_DIRS}
  ${msg_interfaces_INCLUDE_DIRS}
  # ${PROJ_INCLUDE_DIRS}
  ${projection_INCLUDE_DIRS}
  ${PCL_INCLUDE_DIRS}
  common/
  #architecture/lidar_cells/include/
  #architecture/lidar_objs/include/
  communication/include/
  # ${lib_path}
  ${EIGEN3_INCLUDE_DIR}
  architecture/
  architecture/lidar_cells)
# ------- auto-generate protobuf .cpp and .hpp files ----------

# proto source dir (where *.proto file exists)
set(PROTO_SOURCE_DIR ${CMAKE_SOURCE_DIR}/proto)
message("--> protobuf (*.proto) source directory:")
message(${PROTO_SOURCE_DIR})

# proto output dir (where the compiled .ph.cc and pb.h generated)
set(PROTO_OUT_DIR ${CMAKE_BINARY_DIR}/proto)
message("--> protobuf (*.pb.cc, *.pb.h) output directory:")
message(${PROTO_OUT_DIR})
if(EXISTS "${PROTO_OUT_DIR}" AND IS_DIRECTORY "${PROTO_OUT_DIR}")  # exist and is a valid directory
    message(${PROTO_OUT_DIR} "already exists.")
else()
    file(MAKE_DIRECTORY ${PROTO_OUT_DIR})
endif()


# 获取需要编译的proto文件
file(GLOB_RECURSE MSG_PROTOS ${PROTO_SOURCE_DIR}/*.proto)

# 
set(MESSAGE_SRC "")
set(MESSAGE_HDRS "")

# 遍历生成
foreach(msg ${MSG_PROTOS})
    get_filename_component(FIL_WE ${msg} NAME_WE)
    message(${FIL_WE})
    list(APPEND MESSAGE_SRC "${PROTO_OUT_DIR}/${FIL_WE}.pb.cc")
    list(APPEND MESSAGE_HDRS "${PROTO_OUT_DIR}/${FIL_WE}.pb.h")
    # 使用自定义命令
    add_custom_command(
        OUTPUT "${PROTO_OUT_DIR}/${FIL_WE}.pb.cc"
               "${PROTO_OUT_DIR}/${FIL_WE}.pb.h"
        COMMAND  ${PROTOBUF_PROTOC_EXECUTABLE}
        ARGS --cpp_out ${PROTO_OUT_DIR}
             --proto_path ${PROTO_SOURCE_DIR}
             ${FIL_WE}.proto
        DEPENDS ${msg}
        COMMENT "Running C++ protocol buffer compiler on ${msg}"
        VERBATIM
    )
endforeach()

# message(STATUS ${MESSAGE_SRC})
# 设置文件属性为 GENERATED
set_source_files_properties(${MESSAGE_SRC} ${MESSAGE_HDRS} PROPERTIES GENERATED TRUE)
# 添加自定义target
add_custom_target(generate_message ALL
                  DEPENDS ${MESSAGE_SRC} ${MESSAGE_HDRS}
                  COMMENT "generate message target"
                  VERBATIM
)
message("--------------------------------------")
message("--------- Protobuf Compiled ----------")
message("--------------------------------------")
# ------------------------------------------------------------







set(dependencies
  rclcpp 
  rclcpp_components 
  rclcpp_action
  pcl_conversions
  visualization_msgs
  geometry_msgs 
  sensor_msgs
  nav_msgs
  OpenCV
)
# executable
set(MAIN_SRC_LIST
  communication/src/perception.cpp
  communication/src/main.cpp
  communication/src/readconfig.cpp
  architecture/preprocess/preprocess.cpp
  architecture/preprocess/filter/conditional_filter.cpp
  architecture/preprocess/filter/radius_filter.cpp
  architecture/preprocess/filter/voxel_filter.cpp
  architecture/preprocess/filter/removeNan.cpp
  architecture/lidar_cells/lidar_cells_grid.cpp
  architecture/lidar_cells/lidar_cells.cpp
#   architecture/lidar_cells/cluster/dbscan.cpp
  architecture/lidar_cells/cluster/euclidean_cluster.cpp
  architecture/lidar_cells/classify/classify.cpp
  architecture/lidar_cells/classify/boundingbox.cpp
  architecture/lidar_cells/classify/heading.cpp
  architecture/lidar_cells/classify/lshape.cpp
  architecture/lidar_cells/classify/lshape2.cpp
  architecture/lidar_cells/track/match.cpp
  architecture/lidar_cells/track/km_match.cpp
  architecture/lidar_cells/track/match_center.cpp
  architecture/lidar_cells/track/track.cpp
  architecture/lidar_cells/track/l_shape_tracker.cpp
  architecture/lidar_cells/track/match/Hungarian.cpp
  architecture/lidar_cells/track/kalman/kalman.cpp
  
  architecture/lidar_cells/multi_object_tracker/multi_object_tracker.cpp
  architecture/lidar_cells/multi_object_tracker/kalman_filter/kalman_filter.cpp
  architecture/lidar_cells/multi_object_tracker/kalman_filter/time_delay_kalman_filter.cpp
  architecture/lidar_cells/multi_object_tracker/tracker/model/bicycle_tracker.cpp
  architecture/lidar_cells/multi_object_tracker/tracker/model/big_vehicle_tracker.cpp
  architecture/lidar_cells/multi_object_tracker/tracker/model/multiple_vehicle_tracker.cpp
  architecture/lidar_cells/multi_object_tracker/tracker/model/normal_vehicle_tracker.cpp
  architecture/lidar_cells/multi_object_tracker/tracker/model/tracker_base.cpp
  architecture/lidar_cells/multi_object_tracker/tracker/model/unknown_tracker.cpp
  architecture/lidar_cells/multi_object_tracker/tracker/motion_model/bicycle_motion_model.cpp
  architecture/lidar_cells/multi_object_tracker/tracker/motion_model/ctrv_motion_model.cpp
  architecture/lidar_cells/multi_object_tracker/tracker/motion_model/cv_motion_model.cpp
  architecture/lidar_cells/multi_object_tracker/tracker/motion_model/motion_model_base.cpp
  
 
)
add_executable(${PROJECT_NAME} 
  ${MAIN_SRC_LIST} 
  ${MESSAGE_SRC}
  ${MESSAGE_HDRS}
)
target_link_libraries(${PROJECT_NAME} 
  ${rclcpp_LIBRARIES}
  ${std_msgs_LIBRARIES}
  ${msg_interfaces_LIBRARIES}
  ${PROTOBUF_LIBRARIES}
  ${projection_LIBRARIES}
  # ${lib_} 
  ${OpenCV_LIBRARIES}
  ${PCL_LIBRARIES}
  proj
  
)

# ament dependencies
ament_target_dependencies(${PROJECT_NAME}
  ${dependencies}
)




# install
install(TARGETS
  ${PROJECT_NAME}
  DESTINATION lib/${PROJECT_NAME})
install(DIRECTORY
  launch
  DESTINATION share/${PROJECT_NAME}/
)
install(DIRECTORY
  config
  DESTINATION share/${PROJECT_NAME}/
)
# testing
if(BUILD_TESTING)
  find_package(ament_lint_auto REQUIRED)
  # the following line skips the linter which checks for copyrights
  # uncomment the line when a copyright and license is not present in all source files
  #set(ament_cmake_copyright_FOUND TRUE)
  # the following line skips cpplint (only works in a git repo)
  # uncomment the line when this package is not in a git repo
  #set(ament_cmake_cpplint_FOUND TRUE)
  ament_lint_auto_find_test_dependencies()
endif()

ament_package()
